package com.twd.allcomponent.pay.service;


import cn.hutool.core.util.ObjectUtil;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.twd.allcomponent.pay.WeChatPayUrl;
import com.twd.allcomponent.pay.controller.WeChatPay;
import com.twd.allcomponent.pay.util.WxChatPayCommonUtil;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
 * 微信支付接口封装服务
 */
public class WeChatPayService {
    private static final DecimalFormat df = new DecimalFormat("#");

    /**
     * 微信支付统一预下单接口 请查看接口规则 https://pay.weixin.qq.com/wiki/doc/api/native_sl.php?chapter=9_1
     * shuqingyou 2022/9/16
     * @param weChatPay 参数值appid 商户id等等
     * @return Map<String, Object> NATIVE支付则返回二维码扫描地址
     * @throws Exception
     */
    public static Map<String, Object> Unifiedorder(WeChatPay weChatPay) throws Exception {
        Map<String, Object> ResultMap = new HashMap<String, Object>();
        //todo 创建请求参数
        SortedMap<String, String> req = new TreeMap<String, String>();
        req.put("appid", weChatPay.getAppid());    //公众号
        req.put("mch_id", weChatPay.getMch_id());  // 商户号
        req.put("nonce_str", WXPayUtil.generateNonceStr()); // 32位随机字符串
        req.put("body", weChatPay.getBody()); // 商品描述
        req.put("out_trade_no", weChatPay.getOut_trade_no());   // 商户订单号
        req.put("total_fee", df.format(Double.parseDouble(weChatPay.getTotal_fee()) * 100));    // 标价金额(分)
        req.put("spbill_create_ip", weChatPay.getSpbill_create_ip());   // 终端IP
        req.put("notify_url", weChatPay.getNotify_url());  // 回调地址
        req.put("trade_type", weChatPay.getTrade_type());    // 交易类型
        req.put("attach", weChatPay.getAttach());  // 签名
        if (ObjectUtil.isNotEmpty(weChatPay.getSub_mch_id())) {
            //todo 服务商模式
            req.put("sub_mch_id", weChatPay.getSub_mch_id());//子商户号    微信支付 分配的子商户号
        }
        if (ObjectUtil.isNotEmpty(weChatPay.getTime_expire())) {
            //todo 设置订单结束时间
            //交易结束时间 订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。
            req.put("time_expire", weChatPay.getTime_expire());
        }
        if (ObjectUtil.isNotEmpty(weChatPay.getOpenid())) {
            //todo JSAPI支付
            req.put("openid", weChatPay.getOpenid());//用户标识 trade_type=JSAPI，此参数必传，用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一，如果选择传sub_openid,则必须传sub_appid。下单前需要调用【网页授权获取用户信息: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html 】接口获取到用户的Openid。
        }
        req.put("sign", WXPayUtil.generateSignature(req, weChatPay.getApi_key(), WXPayConstants.SignType.MD5));  // 签名

        //todo 生成要发送的 xml
        String xmlBody = WXPayUtil.generateSignedXml(req, weChatPay.getApi_key());
        System.err.println(String.format("微信支付预下单请求 xml 格式:\n%s", xmlBody));

        //todo 发送 POST 请求 统一下单 API 并携带 xmlBody 内容,然后获得返回接口结果
        String result = WxChatPayCommonUtil.httpsRequest(WeChatPayUrl.Uifiedorder, "POST", xmlBody);
        System.err.println(String.format("%s", result));

        //todo 将返回结果从 xml 格式转换为 map 格式
        Map<String, String> WxResultMap = WXPayUtil.xmlToMap(result);

        //todo 判断通信状态 此字段是通信标识，非交易标识
        if (ObjectUtil.isNotEmpty(WxResultMap.get("return_code")) && WxResultMap.get("return_code").equals("SUCCESS")) {
            //todo 业务结果
            if (WxResultMap.get("result_code").equals("SUCCESS")) {
                //todo 预下单成功
                ResultMap.put("code", 0);
                ResultMap.put("msg", "预下单成功");
                //微信订单号
                ResultMap.put("out_trade_no", weChatPay.getOut_trade_no());
                switch (WxResultMap.get("trade_type")) {
                    case "NATIVE":
                        //二维码地址
                        ResultMap.put("QrCode", WxResultMap.get("code_url"));
                        break;
                    case "MWEB":
                        //二维码地址
                        ResultMap.put("mweb_url", WxResultMap.get("mweb_url"));
                        break;
                    case "JSAPI":
                        //预支付交易会话标识 微信生成的预支付回话标识，用于后续接口调用中使用，该值有效期为2小时
                        ResultMap.put("prepay_id", WxResultMap.get("prepay_id"));
                        break;
                }
            } else {
                //todo 下单失败
                ResultMap.put("code", 2);
                ResultMap.put("msg", WxResultMap.get("err_code_des"));
            }
        } else {
            //todo 通信异常
            ResultMap.put("code", 2);
            ResultMap.put("msg", WxResultMap.get("return_msg"));//当return_code为FAIL时返回信息为错误原因 ，例如 签名失败 参数格式校验错误
        }
        return ResultMap;
    }
}
